package com.hup.utils.swing.screenShot;

import com.hup.utils.commons.hardware.MouseUtil;
import com.hup.utils.swing.screenShot.ScreenShotUtil.ShotType;
import lombok.extern.log4j.Log4j2;

import javax.swing.SwingUtilities;
import java.awt.Cursor;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;

/**
 * 截图的鼠标功能,功能描述:{@link ScreenShotLabel}
 * @apiNote bug20201031:拖拽尺寸时,在上/左边缘会导致选框尺寸为零
 * @author hugan
 * @date 2020/5/10
 */
@Log4j2
class ImageMouseGesture extends MouseAdapter {

    private final ScreenShotLabel label;

    /**
     * 未锁定时:首次按下左键时的[鼠标]坐标,
     */
    private int dragX0, dragY0;
    /**
     * 锁定时,首次按下左键时,[鼠标]位置是否在(横竖轴)选区内;
     * (在选区边缘时就'不是在内'了!可以拖拽选区大小)
     */
    private boolean drag0InsideSelection, drag0InsideX, drag0InsideY;
    /**
     * 锁定时:首次按下左键时的[选区]位置
     */
    private int drag0SelectionX, drag0SelectionY;

    public ImageMouseGesture(ScreenShotLabel label) {
        this.label = label;
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        mouseMoved(e);
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        label.curX = e.getX();
        label.curY = e.getY();
        label.magnifierWindow.updateLocation(label.curX, label.curY);
        if (!label.lockSelection) {
            label.selectRect = label.magicWandHelper.getRect(label.curX, label.curY);
        } else {
            MouseUtil.updateResizeCursor(label.curX, label.curY, label, label.selectRect, 1);
        }
        label.repaint();//总要重绘,更新[放大镜]
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (MouseUtil.isLeftButton(e)) {
            if (!label.lockSelection) {
                log.debug("");
                dragX0 = e.getX();
                dragY0 = e.getY();
            } else {
                dragX0 = e.getX();
                dragY0 = e.getY();
                drag0InsideX = dragX0 > label.selectRect.x && dragX0 < label.selectRect.x + label.selectRect.width - 1;
                drag0InsideY = dragY0 > label.selectRect.y && dragY0 < label.selectRect.y + label.selectRect.height - 1;
                drag0InsideSelection = drag0InsideX && drag0InsideY;
                drag0SelectionX = label.selectRect.x;
                drag0SelectionY = label.selectRect.y;
                log.debug("drag0InsideSelection={}", drag0InsideSelection);
                if (!drag0InsideSelection) {
                    int mX = dragX0;
                    int mY = dragY0;
                    if (mX < label.selectRect.x) {
                        label.selectRect.width += (label.selectRect.x - mX);
                        label.selectRect.x = mX;
                        //这句是[选区外拖拽]逻辑的关键,很难理解,意会
                        drag0SelectionX = label.selectRect.x + label.selectRect.width - 1;
                    } else if (mX > label.selectRect.x + label.selectRect.width - 1) {
                        label.selectRect.width = mX - label.selectRect.x + 1;
                    }
                    if (mY < label.selectRect.y) {
                        label.selectRect.height += (label.selectRect.y - mY);
                        label.selectRect.y = mY;
                        drag0SelectionY = label.selectRect.y + label.selectRect.height - 1;
                    } else if (mY > label.selectRect.y + label.selectRect.height - 1) {
                        label.selectRect.height = mY - label.selectRect.y + 1;
                    }
                }
                label.repaint();
            }
        }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (SwingUtilities.isLeftMouseButton(e)) {
            label.curX = e.getX();
            label.curY = e.getY();
            label.magnifierWindow.updateLocation(label.curX, label.curY);
            if (!label.lockSelection) {
                //首次按下并开始拖拽,直接重新定义选区,在释放鼠标后才更新成lock状态
                label.selectRect.x = Math.min(label.curX, dragX0);
                label.selectRect.width = Math.abs(dragX0 - label.curX) + 1;
                label.selectRect.y = Math.min(label.curY, dragY0);
                label.selectRect.height = Math.abs(dragY0 - label.curY) + 1;
            } else {
                if (drag0InsideSelection) {
                    //拖拽前,鼠标在选区内,移动选区
                    int diffX = label.curX - dragX0;
                    int diffY = label.curY - dragY0;
                    label.selectRect.x = drag0SelectionX + diffX;
                    label.selectRect.y = drag0SelectionY + diffY;

                    label.fixMovedRect();
                } else {
                    //拖拽前,鼠标在选区外,重新定义选区
                    if (!drag0InsideX) {
                        //drag0InsideX/Y:实现限制,只拖拽一个轴的功能
                        label.selectRect.x = Math.min(label.curX, drag0SelectionX);
                        label.selectRect.width = Math.abs(drag0SelectionX - label.curX) + 1;
                    }
                    if (!drag0InsideY) {
                        label.selectRect.y = Math.min(label.curY, drag0SelectionY);
                        label.selectRect.height = Math.abs(drag0SelectionY - label.curY) + 1;
                    }
                }
            }
            label.repaint();
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (MouseUtil.isLeftButton(e)) {
            if (!label.lockSelection) {
                label.lockSelection = true;
                label.repaint();//重绘放大镜信息
            }
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        ShotType shotType = label.callback.shotType();
        if (MouseUtil.isLeftButton(e)) {
            if (!label.lockSelection) {
                label.lockSelection = true;
            }
            if (e.getClickCount() >= shotType.applyClickCount) {
                label.applyResult();
            }
        } else if (MouseUtil.isRightButton(e)) {
            if (!label.lockSelection) {
                label.callback.getFrame().dispose();
            } else {
                label.lockSelection = false;
                label.setCursor(Cursor.getDefaultCursor());
                label.repaint();//重绘放大镜信息
            }
        }
    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
        if (!label.lockSelection) {
            boolean isUp = MouseUtil.isUp(e);
            log.debug("isUp={}", isUp);
            label.rgbThreshold += isUp ? 1 : -1;
            if (label.rgbThreshold < 0) {
                label.rgbThreshold = 0;
            } else if (label.rgbThreshold > 255) {
                label.rgbThreshold = 0;
            }
            label.selectRect = label.magicWandHelper.getRect(label.curX, label.curY);
            label.repaint();
        }
    }
}
